package com.mk.es.service.transport;

import com.alibaba.fastjson.JSON;

import com.mk.es.service.transport.entity.EsQueryBuilder;
import com.mk.es.service.transport.entity.EsQueryResult;
import com.mk.es.service.transport.handler.AbstractEsSearchResponseHandlerAdapter;
import com.mk.es.service.transport.handler.EsSearchResponseHandler;
import com.mk.es.service.transport.pool.EsTransportClientPool;
import org.elasticsearch.action.admin.indices.close.CloseIndexRequestBuilder;
import org.elasticsearch.action.admin.indices.close.CloseIndexResponse;
import org.elasticsearch.action.admin.indices.create.CreateIndexRequestBuilder;
import org.elasticsearch.action.admin.indices.create.CreateIndexResponse;
import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequestBuilder;
import org.elasticsearch.action.admin.indices.delete.DeleteIndexResponse;
import org.elasticsearch.action.admin.indices.exists.indices.IndicesExistsRequestBuilder;
import org.elasticsearch.action.admin.indices.exists.types.TypesExistsRequestBuilder;
import org.elasticsearch.action.admin.indices.flush.FlushRequestBuilder;
import org.elasticsearch.action.admin.indices.flush.FlushResponse;
import org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequestBuilder;
import org.elasticsearch.action.admin.indices.mapping.put.PutMappingResponse;
import org.elasticsearch.action.admin.indices.open.OpenIndexRequestBuilder;
import org.elasticsearch.action.admin.indices.open.OpenIndexResponse;
import org.elasticsearch.action.admin.indices.refresh.RefreshRequestBuilder;
import org.elasticsearch.action.admin.indices.refresh.RefreshResponse;
import org.elasticsearch.action.admin.indices.settings.put.UpdateSettingsRequestBuilder;
import org.elasticsearch.action.admin.indices.settings.put.UpdateSettingsResponse;
import org.elasticsearch.action.bulk.BulkRequestBuilder;
import org.elasticsearch.action.bulk.BulkResponse;
import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.action.delete.DeleteRequestBuilder;
import org.elasticsearch.action.delete.DeleteResponse;
import org.elasticsearch.action.get.GetRequestBuilder;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexRequestBuilder;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchRequestBuilder;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.search.SearchType;
import org.elasticsearch.action.update.UpdateRequestBuilder;
import org.elasticsearch.action.update.UpdateResponse;
import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.rest.RestStatus;
import org.elasticsearch.script.ScriptType;
import org.elasticsearch.script.mustache.SearchTemplateRequestBuilder;
import org.elasticsearch.search.aggregations.AggregationBuilder;
import org.elasticsearch.search.sort.SortBuilder;
import org.elasticsearch.search.sort.SortOrder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutionException;

/**
 * ES 客户端操作类
 */
@Component("esTransportOpt")
public class EsTransportOpt {
    Logger logger = LoggerFactory.getLogger(EsTransportOpt.class);

    @Autowired
    private EsTransportClientPool esTransportClientPool;

    /**
     * 获取连接
     * @return
     * @throws Exception
     */
    private TransportClient getClient() throws Exception {
        return esTransportClientPool.getClient();
    }

    /**
     * 释放 连接对象
     * @param client
     */
    private void releaseClient(TransportClient client){
        esTransportClientPool.releaseClient(client);
    }

    //---------------------------------index start-----------------------------------------------

    /**
     * 判断索引index是否存在
     * @param client
     * @param index
     * @return
     */
    private boolean existIndex(TransportClient client, String index){
        IndicesExistsRequestBuilder indicesExistsRequestBuilder = client.admin().indices().prepareExists(index);
        return indicesExistsRequestBuilder.get().isExists();
    }

    /**
     * 判断索引类型type是否存在
     * @param client
     * @param index
     * @return
     */
    private boolean existIndex(TransportClient client, String[] index, String... type) throws ExecutionException, InterruptedException {
        TypesExistsRequestBuilder typesExistsRequestBuilder = client.admin().indices().prepareTypesExists(index).setTypes(type);
        return typesExistsRequestBuilder.get().isExists();
    }

    /**
     * 创建索引
     *  如果索引index已存在，则抛出异常
     * @param client
     * @param index
     * @return
     */
    private boolean creatingIndex(TransportClient client, String index){
        CreateIndexRequestBuilder createIndexRequestBuilder = client.admin().indices().prepareCreate(index);
        CreateIndexResponse createIndexResponse = createIndexRequestBuilder.get();
        return createIndexResponse.isAcknowledged();
    }

    /**
     * 创建索引
     *  如果索引index已存在，则抛出异常
     * @param client
     * @param index
     * @return
     */
    private boolean creatingIndex(TransportClient client, String index, Map<String, ?> settingsMap){
        CreateIndexRequestBuilder createIndexRequestBuilder = client.admin().indices().prepareCreate(index);
        if(settingsMap!=null && !settingsMap.isEmpty()){
            createIndexRequestBuilder.setSettings(settingsMap);
        }

        CreateIndexResponse createIndexResponse = createIndexRequestBuilder.get();
        return createIndexResponse.isAcknowledged();
    }

    /**
     * 创建索引
     *  如果索引index已存在，则抛出异常
     * @param client
     * @param index
     * @param settingsAndMapping 格式{ "settings": {"number_of_shards": 6},"mappings" : { "类型" : { "properties" : { "字段" : { "type" : "text" } } } } } 可以只设置settings
     * @return
     */
    private boolean creatingIndex(TransportClient client, String index, String settingsAndMapping) {
        CreateIndexRequestBuilder createIndexRequestBuilder = client.admin().indices().prepareCreate(index).setSource(settingsAndMapping, XContentType.JSON);

        CreateIndexResponse createIndexResponse = createIndexRequestBuilder.get();
        return createIndexResponse.isAcknowledged();
    }

    /**
     * 关闭索引index
     * @param client
     * @param indices
     * @return
     */
    private boolean closeIndex(TransportClient client, String... indices){
        //关闭索引
        CloseIndexRequestBuilder closeIndexRequestBuilder = client.admin().indices().prepareClose(indices);

        CloseIndexResponse closeIndexResponse = closeIndexRequestBuilder.get();
        return closeIndexResponse.isAcknowledged();
    }

    /**
     * 打开索引index
     * @param client
     * @param indices
     * @return
     */
    private boolean openIndex(TransportClient client, String... indices){
        //打开索引
        OpenIndexRequestBuilder openIndexRequestBuilder = client.admin().indices().prepareOpen(indices);

        OpenIndexResponse openIndexResponse = openIndexRequestBuilder.get();
        return openIndexResponse.isAcknowledged();
    }

    /**
     * 重新刷新索引index
     * @param client
     * @param indices
     * @return
     */
    private int refreshIndex(TransportClient client, String... indices){
        //重新刷新索引
        RefreshRequestBuilder refreshRequestBuilder = client.admin().indices().prepareRefresh(indices);

        RefreshResponse refreshResponse = refreshRequestBuilder.get();
        return refreshResponse.getSuccessfulShards();
    }

    /**
     * 刷新索引index
     * @param client
     * @param indices
     * @return
     */
    private int flushIndex(TransportClient client, String... indices){
        //刷新索引
        FlushRequestBuilder flushRequestBuilder = client.admin().indices().prepareFlush(indices);

        FlushResponse flushResponse = flushRequestBuilder.get();
        return flushResponse.getSuccessfulShards();
    }

    /**
     * 删除索引
     * @param indices 索引数组index
     */
    public boolean deleteIndices(String... indices) {
        TransportClient client = null;
        try {
            //获取客户端
            client = getClient();

            DeleteIndexRequestBuilder deleteIndexRequestBuilder = client.admin().indices().prepareDelete(indices);
            logger.debug("elasticSearch deleteIndices dsl =》{}", deleteIndexRequestBuilder.toString());

            DeleteIndexResponse deleteIndexResponse = deleteIndexRequestBuilder.get();

            //刷新索引
            this.flushIndex(client,indices);
            return deleteIndexResponse.isAcknowledged();
        } catch (Exception e) {
            logger.error("EsTransportOpt updateIndexSettings error", e);
        } finally {
            releaseClient(client); //释放
        }
        return false;
    }

    /**
     * 更新索引Settings
     * @param settingsMap
     * @param index
     * @return
     */
    public boolean updateIndexSettings(Map<String, String> settingsMap, String index) {
        TransportClient client = null;
        try {
            if(settingsMap!=null && !settingsMap.isEmpty()){
                //获取客户端
                client = getClient();
                //如果索引不存在，则先创建索引
                if(!existIndex(client, index)){
                    creatingIndex(client, index);
                }

                UpdateSettingsRequestBuilder updateSettingsRequestBuilder = client.admin().indices().prepareUpdateSettings(index).setSettings(Settings.builder().put(settingsMap));

                UpdateSettingsResponse updateSettingsResponse = updateSettingsRequestBuilder.get();
                return updateSettingsResponse.isAcknowledged();
            }
        } catch (Exception e) {
            logger.error("EsTransportOpt updateIndexSettings error", e);
        } finally {
            releaseClient(client); //释放
        }
        return false;
    }

    /**
     * 判断索引类型type是否存在
     * @param client
     * @param index
     * @param type
     * @return
     */
    private boolean existIndexType(TransportClient client, String index, String type){
        TypesExistsRequestBuilder typesExistsRequestBuilder = client.admin().indices().prepareTypesExists(index).setTypes(type);

        return typesExistsRequestBuilder.get().isExists();
    }

    /**
     * 添加索引类型Mapping
     * @param index
     * @param type
     * @param mapping  格式{"properties": {"字段": {"type": "text"}}}
     * @return
     */
    public boolean putMapping(String index, String type, String mapping) {
        TransportClient client = null;
        try {
            //获取客户端
            client = getClient();
            //如果索引不存在，则先创建索引
            if(!existIndex(client, index)){
                creatingIndex(client, index);
            }

            PutMappingRequestBuilder putMappingRequestBuilder = client.admin().indices().preparePutMapping(index).setType(type)
                    .setSource(mapping, XContentType.JSON);

            PutMappingResponse putMappingResponse = putMappingRequestBuilder.get();
            return putMappingResponse.isAcknowledged();
        } catch (Exception e) {
            logger.error("EsTransportOpt addMapping error", e);
        } finally {
            releaseClient(client); //释放
        }
        return false;
    }


    //---------------------------------index end  -----------------------------------------------
    //---------------------------------document start-----------------------------------------------

    /**
     * 添加文档
     * @param index
     * @param type
     * @param id
     * @param jsonStr
     * @return
     */
    public void addDocument(String index, String type, String id, String jsonStr) {
        TransportClient client = null;
        try {
            //获取客户端
            client = getClient();
            IndexRequestBuilder indexRequestBuilder = client.prepareIndex(index, type, id).setSource(jsonStr, XContentType.JSON);
            logger.debug("elasticSearch addDocument dsl =》{}", indexRequestBuilder.request().toString());

            indexRequestBuilder.get();
        } catch (Exception e) {
            logger.error("EsTransportOpt addDocument error", e);
        } finally {
            releaseClient(client); //释放
        }
    }

    /**
     * 添加文档
     * @param index
     * @param type
     * @param id
     * @param object
     * @return
     */
    public void addDocument(String index, String type, String id, Object object) {
        this.addDocument(index, type, id, JSON.toJSONString(object));
    }

    /**
     * 更新文档
     * @param index
     * @param type
     * @param id
     * @param object
     * @return
     */
    public void updateDocument(String index, String type, String id, Object object) {
        TransportClient client = null;
        try {
            //获取客户端
            client = getClient();
            UpdateRequestBuilder updateRequestBuilder = client.prepareUpdate(index, type, id).setDoc(JSON.toJSONString(object), XContentType.JSON);
            logger.debug("elasticSearch updateDocument dsl =》{}", updateRequestBuilder.toString());

            UpdateResponse updateResponse = updateRequestBuilder.get();
            RestStatus status = updateResponse.status();
        } catch (Exception e) {
            logger.error("EsTransportOpt addDocument error", e);
        } finally {
            releaseClient(client); //释放
        }
    }

    /**
     * 更新部分文档
     * @param index
     * @param type
     * @param id
     * @param map
     * @return
     */
    public void updatePartDocument(String index, String type, String id, Map<String, Object> map) {
        TransportClient client = null;
        try {
            //获取客户端
            client = getClient();

            UpdateRequestBuilder updateRequestBuilder = client.prepareUpdate(index, type, id).setDoc(map);
            logger.debug("elasticSearch updatePartDocument dsl =》{}", updateRequestBuilder.toString());

            UpdateResponse updateResponse = updateRequestBuilder.get();
        } catch (Exception e) {
            logger.error("EsTransportOpt addDocument error", e);
        } finally {
            releaseClient(client); //释放
        }
    }

    /**
     * 删除文档
     * @param index
     * @param type
     * @param id
     * @return
     */
    public boolean delDocument(String index, String type, String id) {
        TransportClient client = null;
        try {
            //获取客户端
            client = getClient();

            DeleteRequestBuilder deleteRequestBuilder = client.prepareDelete(index, type, id);

            DeleteResponse deleteResponse = deleteRequestBuilder.get();
            RestStatus status = deleteResponse.status();
            return RestStatus.OK.equals(status);
        } catch (Exception e) {
            logger.error("EsTransportOpt delDocument error", e);
        } finally {
            releaseClient(client); //释放
        }
        return false;
    }

    /**
     * 批量保存对象
     * @param index
     * @param type
     * @param objectMap
     * @return
     */
    public boolean batchAddDocument(String index, String type, Map<String, Object> objectMap) {
        TransportClient client = null;
        try {
            //获取客户端
            client = getClient();

            // 批量处理request
            BulkRequestBuilder bulkRequest = client.prepareBulk();
            for (Map.Entry<String, Object> entry: objectMap.entrySet()) {
                if(entry == null) {
                    continue;
                }
                bulkRequest.add(new IndexRequest(index, type, entry.getKey()).source(JSON.toJSONBytes(entry.getValue()), XContentType.JSON));
            }

            // 执行批量处理request
            BulkResponse bulkResponse = bulkRequest.get();
            boolean result = !bulkResponse.hasFailures();
            // 处理错误信息
            if (bulkResponse.hasFailures()) {
                logger.error("EsTransportOpt batchAddDocument error ==>{}", bulkResponse.buildFailureMessage());
            }

            return result;
        } catch (Exception e) {
            logger.error("EsTransportOpt batchAddDocument error", e);
        } finally {
            releaseClient(client); //释放
        }
        return false;
    }

    /**
     * 批量删除对象
     * @param index
     * @param type
     * @param idList
     * @return
     */
    public boolean batchDelDocument(String index, String type, List<String> idList) {
        TransportClient client = null;
        try {
            if (idList!=null && !idList.isEmpty()) {
                return false;
            }

            //获取客户端
            client = getClient();

            BulkRequestBuilder requestBuilder = client.prepareBulk();
            for (String id : idList) {
                requestBuilder.add(new DeleteRequest(index, type, id));
            }

            BulkResponse bulkResponse = requestBuilder.get();
            boolean result = !bulkResponse.hasFailures();
            // 处理错误信息
            if (bulkResponse.hasFailures()) {
                logger.error("EsTransportOpt batchDelDocument error ==>>{}", bulkResponse.buildFailureMessage());
            }

            return result;
        } catch (Exception e) {
            logger.error("EsTransportOpt batchDelDocument error", e);
        } finally {
            releaseClient(client); //释放
        }
        return false;
    }

    /**
     * 获取文档信息
     * @param index
     * @param type
     * @param id
     * @param clazz
     * @param <T>
     * @return
     */
    public <T> T getDocument(String index, String type, String id, Class<T> clazz) {
        TransportClient client = null;
        try {
            //获取客户端
            client = getClient();
            GetRequestBuilder getRequestBuilder = client.prepareGet(index, type, id);

            GetResponse response = getRequestBuilder.get();
            if(response.isExists()){
                return JSON.parseObject(response.getSourceAsBytes(), clazz);
            }
        } catch (Exception e) {
            logger.error("EsTransportOpt getDocument error", e);
        } finally {
            releaseClient(client); //释放
        }
        return null;
    }

    /**
     * 获取文档json数据
     * @param index
     * @param type
     * @param id
     * @return
     */
    public String getDocumentJson(String index, String type, String id) {
        TransportClient client = null;
        try {
            //获取客户端
            client = getClient();

            GetRequestBuilder getRequestBuilder = client.prepareGet(index, type, id);

            GetResponse response = getRequestBuilder.get();
            if(response.isExists()){
                return response.getSourceAsString();
            }
        } catch (Exception e) {
            logger.error("EsTransportOpt getDocument error", e);
        } finally {
            releaseClient(client); //释放
        }
        return null;
    }

    //---------------------------------document end  -----------------------------------------------

    //---------------------------------query start-----------------------------------------------

    /**
     * 通过内敛脚本方式来查询
     * @param index 索引
     * @param type 索引类型
     * @param queryJsonStr 查询脚本
     * @param templateParams 查询脚本参数，替换的是查询脚本的{{}}
     * @param clazz 返回实体的Class
     * @param handlerAdapter 处理类
     * @param <T>
     * @return
     */
    private <T> EsQueryResult<T> inlineTemplatesQuerySearch(String index, String type, String queryJsonStr, Map<String, Object> templateParams, Class<T> clazz, EsSearchResponseHandler<T> handlerAdapter){
        TransportClient client = null;
        try {
            client = getClient();
            SearchTemplateRequestBuilder searchTemplateRequestBuilder = new SearchTemplateRequestBuilder(client)
                    .setScript(queryJsonStr) //查询脚本语句
                    .setScriptType(ScriptType.INLINE) //内敛脚本查询
                    .setScriptParams(templateParams) //查询参数
                    .setRequest(new SearchRequest().indices(index).types(type));

            logger.debug("elasticSearch inlineTemplatesQuerySearch dsl =》{}", searchTemplateRequestBuilder.toString());

            SearchResponse response = searchTemplateRequestBuilder.get().getResponse();
            //通过处理类来包装
            return handlerAdapter.handle(response, clazz);
        } catch (Exception e) {
            logger.error("EsTransportOpt inlineTemplatesSearchQuery error", e);
        } finally {
            releaseClient(client); //释放
        }
        return null;
    }

    /**
     * 通过脚本方式来查询
     * @param index 索引
     * @param type 索引类型
     * @param queryJsonStr 查询脚本
     * @param params 查询脚本参数，替换的是查询脚本的{{}}
     * @param clazz 返回实体的Class
     * @param handlerAdapter 处理类
     * @param <T>
     * @return
     */
    public <T> EsQueryResult<T> querySearch(String index, String type, String queryJsonStr, Map<String, Object> params, Class<T> clazz, EsSearchResponseHandler<T> handlerAdapter){
        return inlineTemplatesQuerySearch(index, type, queryJsonStr, params, clazz, handlerAdapter);
    }

    /**
     * 通过脚本方式来查询
     * @param index 索引
     * @param type 索引类型
     * @param queryJsonStr ES查询语句
     * @param params 查询语句对应的参数，替换的是查询脚本的{{}}
     * @return
     */
    public <T> EsQueryResult<T> querySearch(String index, String type, String queryJsonStr, Map<String, Object> params, Class<T> clazz) {
        //调用模板查询
        return inlineTemplatesQuerySearch(index, type, queryJsonStr, params, clazz, new AbstractEsSearchResponseHandlerAdapter<T>(){});
    }

    /**
     *  通过语句查询
     * @param index
     * @param type
     * @param esQueryBuilder
     * @param clazz
     * @param handlerAdapter
     * @param <T>
     * @return
     * @throws Exception
     */
    private <T> EsQueryResult<T> querySearch(TransportClient client, String index, String type, EsQueryBuilder esQueryBuilder, Class<T> clazz, EsSearchResponseHandler<T> handlerAdapter) throws InstantiationException, IllegalAccessException {
        SearchRequestBuilder searchRequestBuilder = client.prepareSearch(index).setSearchType(SearchType.DFS_QUERY_THEN_FETCH);

        //索引类型type
        if(type != null){
            searchRequestBuilder.setTypes(type);
        }

        //查询
        if(esQueryBuilder.getQueryBuilder() != null){
            searchRequestBuilder.setQuery(esQueryBuilder.getQueryBuilder());
        }

        //高亮字段
        if(esQueryBuilder.getHighlightBuilder() != null){
            searchRequestBuilder.highlighter(esQueryBuilder.getHighlightBuilder());
        }

        //聚合
        if(esQueryBuilder.getAggregations() != null && !esQueryBuilder.getAggregations().isEmpty()){
            for (AggregationBuilder aggregationBuilder: esQueryBuilder.getAggregations()) {
                if(aggregationBuilder ==  null) {
                    continue;
                }
                searchRequestBuilder.addAggregation(aggregationBuilder);
            }
        }

        //
        if(esQueryBuilder.getSuggestBuilder() != null){
            searchRequestBuilder.suggest(esQueryBuilder.getSuggestBuilder());
        }

        //
        if(esQueryBuilder.getPostFilter() != null){
            searchRequestBuilder.setPostFilter(esQueryBuilder.getPostFilter());
        }

        //排序
        if(esQueryBuilder.getSorts() != null && !esQueryBuilder.getSorts().isEmpty()){
            for (SortBuilder sortBuilder: esQueryBuilder.getSorts()) {
                searchRequestBuilder.addSort(sortBuilder);
            }
        }

        //排序
        if(esQueryBuilder.getSortMap() != null && !esQueryBuilder.getSortMap().isEmpty()){
            for (Map.Entry<String, SortOrder> entry: esQueryBuilder.getSortMap().entrySet()) {
                if(entry == null) {
                    continue;
                }
                searchRequestBuilder.addSort(entry.getKey(), entry.getValue());
            }
        }

        //分页开始位置
        if(esQueryBuilder.getFrom() != null){
            searchRequestBuilder.setFrom(esQueryBuilder.getFrom());
        }

        //分页每页显示多少条
        if(esQueryBuilder.getSize() != null){
            searchRequestBuilder.setSize(esQueryBuilder.getSize());
        }

        //查询超时时间
        if(esQueryBuilder.getTimeout() != null){
            searchRequestBuilder.setTimeout(esQueryBuilder.getTimeout());
        }

        //
        if(esQueryBuilder.getMinScore() != null){
            searchRequestBuilder.setMinScore(esQueryBuilder.getMinScore());
        }

        //
        if(esQueryBuilder.getExplain() != null){
            searchRequestBuilder.setExplain(esQueryBuilder.getExplain());
        }

        //
        if(esQueryBuilder.getVersion() != null){
            searchRequestBuilder.setVersion(esQueryBuilder.getVersion());
        }

        //
        if(esQueryBuilder.getDocValueFields() != null && !esQueryBuilder.getDocValueFields().isEmpty()){
            for (String docValueField : esQueryBuilder.getDocValueFields()) {
                if(docValueField == null) {
                    continue;
                }
                searchRequestBuilder.addDocValueField(docValueField);
            }
        }

        //
        if(esQueryBuilder.getStoredFields() != null && !esQueryBuilder.getStoredFields().isEmpty()){
            for (String storedField : esQueryBuilder.getStoredFields()) {
                if(storedField == null) {
                    continue;
                }
                searchRequestBuilder.addStoredField(storedField);
            }
        }

        logger.debug("elasticSearch query dsl =》{}", searchRequestBuilder.toString());

        SearchResponse searchResponse = searchRequestBuilder.get();

        //通过处理类来包装
        return handlerAdapter.handle(searchResponse, clazz);
    }

    /**
     *  通过语句查询
     * @param index
     * @param type
     * @param esQueryBuilder
     * @param clazz
     * @param handlerAdapter
     * @param <T>
     * @return
     * @throws Exception
     */
    public <T> EsQueryResult<T> querySearch(String index, String type, EsQueryBuilder esQueryBuilder, Class<T> clazz, EsSearchResponseHandler<T> handlerAdapter) {
        TransportClient client = null;
        try {
            //获取客户端
            client = getClient();
            //查询
            return querySearch(client, index, type, esQueryBuilder, clazz, handlerAdapter);
        } catch (Exception e) {
            logger.error("EsTransportOpt inlineTemplatesSearchQuery error", e);
        } finally {
            releaseClient(client); //释放
        }
        return null;
    }

    /**
     * 通过语句查询
     * @param index 索引
     * @param type 索引类型
     * @param esQueryBuilder ES查询语句
     * @return
     */
    public <T> EsQueryResult<T> querySearch(String index, String type, EsQueryBuilder esQueryBuilder, Class<T> clazz) {
        //调用模板查询
        return querySearch(index, type, esQueryBuilder, clazz, new AbstractEsSearchResponseHandlerAdapter<T>(){});
    }

    //---------------------------------query end  -----------------------------------------------

}
